//////////////////////////////////////////////////////////////////////////

#ifndef _CLIENTCONNECTIONIMPL_H_
#define _CLIENTCONNECTIONIMPL_H_

//////////////////////////////////////////////////////////////////////////

#ifndef _CONNECTIONIMPL_H_
#include "connectionimpl.h"
#endif

#include <boost/asio.hpp>

//////////////////////////////////////////////////////////////////////////

using boost::system::error_code;
using boost::asio::ip::tcp;
using boost::asio::ip::udp;
class InnerPacket;

//////////////////////////////////////////////////////////////////////////


/** Connection implementation for client
*
*
*  @author   Pasechnik Roman
*  @author   Anastasia Karpinska
*  @since    Jun 30th, 2009
*  @updated  Nov 21th, 2009
*/
class ClientConnectionImpl : public ConnectionImpl
{
//////////////////////////////////////////////////////////////////////////

public:

//////////////////////////////////////////////////////////////////////////


    /** Constructor */
    ClientConnectionImpl();


    /** Destructor */
    virtual ~ClientConnectionImpl();


//////////////////////////////////////////////////////////////////////////


    /** Send TCP */
    virtual void SendTCP( const NetworkPacket& _data );


    /** Send UDP */
    virtual void SendUDP( const NetworkPacket& _data );


//////////////////////////////////////////////////////////////////////////


    /** Accept new connection (empty implementation here, this is for server only) */
    virtual void Accept();


    /** Connect to server */
    virtual void Connect( const char* _address );


    /** Close connection */
    virtual void Close();


//////////////////////////////////////////////////////////////////////////


    /** Is client connected to server */
    virtual bool IsConnected() const;


//////////////////////////////////////////////////////////////////////////

private:

//////////////////////////////////////////////////////////////////////////


    /** Start receive UDP packets */
    void StartReceiveTCP();


    /** Start receive TCP packets */
    void StartReceiveUDP();


//////////////////////////////////////////////////////////////////////////


    /** Inner call, send TCP packet*/
    void SendTCPInner( const NetworkPacket& _data );


    /** Inner call, send UDP packet*/
    void SendUDPInner( const NetworkPacket& _data );


//////////////////////////////////////////////////////////////////////////


    /** Handle sent TCP packet */
    void HandleSendTCP( const error_code& _error,
                        size_t _bytesTransferred );


//////////////////////////////////////////////////////////////////////////


    /** Handle received TCP packet */
    void HandleRecvTCP( const error_code& _error,
                        size_t _bytesTransferred );


    /** Handle received regular TCP packet */
    void HandleRecvTCPRegular( const InnerPacket& _innerPacket );


    /** Handle received connect TCP packet */
    void HandleRecvTCPConnect( const InnerPacket& _innerPacket );


////////////////////////////////////////////////////////////////////////////////


    /** Handle received UDP packet */
    void HandleRecvUDP( const error_code& _error,
                        size_t _bytesTransferred );


    /** Handle received regular UDP packet */
    void HandleRecvUDPRegular( const InnerPacket& _innerPacket );


////////////////////////////////////////////////////////////////////////////////

private:

////////////////////////////////////////////////////////////////////////////////
//// Sockets
////////////////////////////////////////////////////////////////////////////////


    /** TCP socket */
    tcp::socket m_TCPSocket;


    /** UDP socket */
    udp::socket m_UDPSocket;
    

    /** UDP endpoint of server [Server address] */
    udp::endpoint m_UDPEndPoint;


////////////////////////////////////////////////////////////////////////////////
//// Connection establishment
////////////////////////////////////////////////////////////////////////////////


    /** Establish TCP connection with server. Returns true on success */
    bool EstablishTCP( const char* _address );


    /** Establish UDP connection with server */
    void EstablishUDP( const char* _address );


    /** Is UDP confirmed */
    bool IsUDPConfirmed();


    /** Confirm UDP */
    void ConfirmUDP();


//////////////////////////////////////////////////////////////////////////


    /** Confirmation packet for UDP socket */
    NetworkPacket m_Confirmation;


    /** Flag is true if UDP connection was confirmed by server */
    bool m_UDPConfirmed;


    /** True when TCP endpoint received from server */ 
    bool m_IsEndpointReceived;


//////////////////////////////////////////////////////////////////////////
};

//////////////////////////////////////////////////////////////////////////

#endif

//////////////////////////////////////////////////////////////////////////
